﻿using System;

namespace MyLib {
	/// <summary>
	/// 
	/// </summary>
	public class AggregateDbContextProvider : DbContextProvider {
		private const int MaxFanOut = 8;

		private DbContextProvider[] m_dependencies = new DbContextProvider[MaxFanOut];

		private int m_depCount = 0;

		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <returns></returns>
		protected T GetDependency<T>() where T : DbContextProvider, new() {
			return GetDependency<T>(IdGenerator);
		}

		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <param name="idGenerator"></param>
		/// <returns></returns>
		protected T GetDependency<T>(IUniqueIdGenerator idGenerator) where T : DbContextProvider, new() {
			var ct = FindDependency<T>();

			if (ct == null) {
				System.Diagnostics.Debug.Assert(m_depCount < MaxFanOut, "At most " + MaxFanOut + " dependencies allowed.");

				// TODO: Check circle dependency.
				ct = new T();

				ct.SessionFactory = this.SessionFactory;
				ct.IdGenerator = idGenerator;

				m_dependencies[m_depCount++] = ct;
			}

			return ct;
		}

		/// <summary>
		/// 
		/// </summary>
		public override SessionFactory SessionFactory {
			get {
				return base.SessionFactory;
			}
			set {
				base.SessionFactory = value;

				for (var i = 0; i < m_depCount; i++) {
					var dep = m_dependencies[i];

					dep.SessionFactory = value;
				}
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <typeparam name="T"></typeparam>
		/// <returns></returns>
		private T FindDependency<T>() where T : DbContextProvider {
			var qt = typeof(T);
			for (var i = 0; i < m_depCount; i++) {
				var dep = m_dependencies[i];

				if (qt.IsAssignableFrom(dep.GetType())) {
					return (T)dep;
				}
			}

			return null;
		}
	} // end of AggregateDbContextProvider.
}
